<template>
  <div class="flex flex-col h-full">
    <div class="flex-shrink-0">
      <el-button type="primary" @click="() => onShowPersonEditDialog()">
        新增
      </el-button>
      <el-button type="danger" @click="onDelIds">删除</el-button>
    </div>
    <div class="flex-shrink-0">
      <div v-html="htmlContent"></div>
    </div>
    <div class="flex-1 h-0">
      <JsonPageTable
        ref="JsonPageTableRef"
        v-model:pageSize="pageSize"
        v-model:currentPage="currentPage"
        :enable-pagination="true"
        :el-pagination-props="{
          layout: 'total, sizes, prev, pager, next, jumper',
          'page-sizes': [3, 10, 20, 30, 50],
        }"
        :selection-column="true"
        :el-table-evt="elTableEvt"
        :load-page-data-method="loadDataMethod"
        :column-arr="columnArr"
        :index-column="true"
        :pending-promise-key-builder-method="pendingPromiseKeyBuilderMethod"
        :enable-auto-cancel-diff-key-pending-promise="true"
        :enable-shared-same-key-pending-promise="true"
        @data-load-suc="onDataLoadSuc"
      >
        <template #operate="{ scope }">
          <el-popconfirm
            title="执行删除操作?"
            @confirm="onDelId(scope.row.idx)"
          >
            <template #reference>
              <el-link type="danger"> 删除 </el-link>
            </template>
          </el-popconfirm>
          &nbsp;
          <el-link type="primary" @click="onShowPersonEditDialog(scope.row)">
            编辑
          </el-link>
        </template>
      </JsonPageTable>
    </div>
    <PersonEditDialog
      v-model:visible="PersonEditDialogVisible"
      :init-data="initData"
      @save="onSave"
    ></PersonEditDialog>
  </div>
</template>

<script setup lang="ts">
// TODO: 请自行删除多余的引用，以及引入typing.d.ts
import {
  JsonPageTable,
  PageParam,
  PageResult,
  TableColumn,
  removeEmptyField,
} from '@ui/base-comp'
import type { JsonPageTableInstance } from '@ui/base-comp'
import '@ui/base-comp/dist/style.css'
import { ref } from 'vue'
import type { Person, PersonEdit, PersonFormData } from './typing.d.ts'
import { axiosInstance } from '@/utils/ajax/AjaxUtil'
import { toRefs } from 'vue'
import { ElMessage } from 'element-plus'
import PersonEditDialog from './PersonEditDialog.vue'
import { usePersonEditDialogHook } from '../hooks/PersonEditDialogHook'
import xss from 'xss'

const props = defineProps<{
  formData: PersonFormData
}>()

const { formData } = toRefs(props)

const JsonPageTableRef = ref<JsonPageTableInstance>()
const htmlContent = ref('')
const { PersonEditDialogVisible, onShowPersonEditDialog, initData } =
  usePersonEditDialogHook()
/**
 * 每页显示记录数
 */
const pageSize = ref<number>(3)
/**
 * 当前页码
 */
const currentPage = ref<number>(1)

interface CustomElSortInfo extends Record<string, unknown> {
  /**
   * 排序方式:
   * descending: 降序
   * ascending: 升序
   * null: 不排序
   */
  order: 'descending' | 'ascending' | null
  prop: string
}
/**
 * 对象的属性名表示排序字段, 对象的属性值表示是否降序
 *
 * 这里之所以不用map是因为map无法序列化
 */
const sortColumnObject: Record<string, boolean> = Object.create({})
function onSortChange(sortColumnData: CustomElSortInfo) {
  console.log('sortColumnData', sortColumnData)
  if (sortColumnData.order === null) {
    delete sortColumnObject[sortColumnData.prop]
  } else {
    sortColumnObject[sortColumnData.prop] =
      sortColumnData.order === 'descending'
  }
  // 这里看实际需求点击排序是否需要将页码重置为第一页
  JsonPageTableRef.value?.refresh(1)
}

/**
 *表格数据加载方法(表格组件内部通过该方法获取数据)
 */
async function loadDataMethod(pageParam: PageParam) {
  // TODO: 请自行完善数据加载方法

  console.log('排序字段和排序方式传给后端：', sortColumnObject)

  const reqParam = {
    ...pageParam,
    ...formData.value,
    sort: sortColumnObject,
  }

  removeEmptyField(reqParam)

  const pageResult = (await axiosInstance.post(
    '/local-mock-api/Person/post',
    reqParam
  )) as PageResult<Person>
  return pageResult
}

/**
 * 给每个pending中的promise设置一个唯一标识(用于并行控制)
 */
function pendingPromiseKeyBuilderMethod(pageParam: PageParam) {
  return JSON.stringify(pageParam)
}

/**
 *表格数据加载成功之后的回调函数
 */
function onDataLoadSuc(pageResult: PageResult<Person> | undefined) {
  // TODO: 请根据需求自行调整代码
  console.log(pageResult)
  const list = pageResult?.list
  if (list && list.length > 0) {
    htmlContent.value = xss(list[0].name)
  } else {
    htmlContent.value = ''
  }
}
// TODO: 请根据自己的需求做相应调整
const selectedRows = ref<number[]>([])
const elTableEvt = {
  'selection-change': (val: Person[]) => {
    // 清空选中项
    selectedRows.value = []
    // val是选中项
    val.forEach(item => {
      selectedRows.value.push(item.idx)
    })
  },
  'sort-change': onSortChange,
}

function onSave(d?: PersonEdit) {
  console.log(d)
  if (d) {
    // 新增成功，则刷回第一页
    JsonPageTableRef.value?.refresh(1)
  } else {
    // 更新成功，则刷新当前页
    JsonPageTableRef.value?.refresh()
  }
}
function onDelId(id: number) {
  axiosInstance.delete(`/local-mock-api/Person/del/${id}`)
  JsonPageTableRef.value?.refresh(1)
}
function onDelIds() {
  if (selectedRows.value.length > 0) {
    JsonPageTableRef.value?.refresh(1)
  } else {
    ElMessage.info('请选择待删除数据!')
  }
}

const columnArr = ref<TableColumn[]>([
  {
    prop: 'name',
    label: '姓名',
  },
  {
    prop: 'male',
    label: '性别',
    dictionaryConvert: (rowData: Person) => {
      return rowData.male === 'male' ? '男' : '女'
    },
  },
  {
    prop: 'age',
    label: '年龄',
    sortable: 'custom',
  },
  {
    prop: 'operate',
    label: '操作',
    slotName: 'operate',
  },
])

defineExpose({ JsonPageTableRef })
</script>

<style scoped lang="scss"></style>
